class MyPromise {
    static PENDING = "pending";
    static REJECTED = "rejected";
    static RESOLVED = "resolved";

    /**
     * resolve  rejected
     * @param {*} excutor 
     */
    constructor(excutor) {
        // 状态
        this.__state = MyPromise.PENDING;
        this.__value = null;
        this.__queueTask = [];
        try {
            // 回调方法
            excutor(this.__resolve.bind(this), this.__rejected.bind(this))
        } catch (error) {
            this.__rejected(error);
        }
    }
    /**
     * 处理队列任务
     */
    __handle_taskQueue() {
        if (this.__queueTask.length > 0) {
            for (let i = 0; i < this.__queueTask.length; i++) {
                const { fn, state} = this.__queueTask[i];
                this.__handle_fn(fn, state);
            }
        }
    }
    /**
     * 成功
     * @param {*} data 
     */
    __resolve(data) {
        if (this.__state !== MyPromise.PENDING) {
            return;
        }
        this.__state = MyPromise.RESOLVED;
        this.__value = data;
        this.__handle_taskQueue();
    }


    /**
     * 失败
     * @param {*} err 
     */
    __rejected(err) {
        if (this.__state !== MyPromise.PENDING) {
            return;
        }
        this.__state = MyPromise.REJECTED;
        this.__value = err;
        this.__handle_taskQueue();
    }


    /**
     *  开始执行微任务
     * @param {*} obj 
     * @returns 
     */
    __microtaskFn(obj) {
        const { fn, state, data } = obj;
        if (typeof fn !== "function" || this.__state !== state) {
            return;
        }
        let fn1 = () => {
            fn(data);
        }


        if (queueMicrotask) {
            queueMicrotask(fn1)
        } else {
            if (process && process.nextTick) {
                process.nextTick(fn1)
            } else if (MutationObserver) {
                let m = new MutationObserver(fn1);
                const div = document.createElement("div");
                m.observe(div, {
                    childList: true
                })
                div.innerText = "1";
            } else {
                setTimeout(fn1, 0);
            }
        }

    }

    __handle_fn(fn, state) {
        if (this.__state === MyPromise.PENDING) {
            this.__queueTask.push({
                fn,
                state,
                data: this.__value
            })
        } else {
            if (this.__state === state) {
                this.__microtaskFn({
                    fn,
                    state,
                    data: this.__value
                });
            }
        }

    }

    /**
     * 回调成功值（执行微任务）
     * @param {*} fn 
     */
    then(fn) {
        this.__handle_fn(fn, MyPromise.RESOLVED)
        return this;
    }

    /**
     * 回调失败值（执行微任务）
     * @param {*} fn 
     */
    catch(fn) {
        this.__handle_fn(fn, MyPromise.REJECTED)
        return this
    }

    static resolve(data) {
        return new MyPromise((resolve, reject) => {
            resolve(data)
        });
    }
    static reject(err) {
        return new MyPromise((resolve, reject) => {
            reject(err)
        });
    }
    static all(args) {
        if (!args.__proto__[Symbol.iterator]) {
            throw (new Error("object is not iterable (cannot read property Symbol(Symbol.iterator))"))
        }
        return new MyPromise((resolve, reject) => {
            let arr = new Array();
            let idx = 0;
            loop: for (let i = 0; i < args.length; i++) {
                const item = args[i];
                if (item[Symbol.toStringTag]() === "MyPromise") {
                    item.then((data) => {
                        idx++;
                        arr[i] = data;
                        if (idx === args.length) {
                            resolve(arr)
                        }
                    }).catch((data) => {
                        reject(data);
                    })
                }
            }
        })
    }
    [Symbol.toStringTag]() {
        return "MyPromise"
    }
}
export default MyPromise